use std::{env, error::Error, fs};
pub struct Config{
    pub query:String,
    pub file_path:String,
    pub ignore_case:bool,
}
impl Config {
    pub fn build(args:&Vec<String>)->Result<Config,&'static str>{
        //期望new函数永远不会出现错误，所以命名build
        if args.len()<3 {
            //panic!("参数不足");
            //对于用户使用，panic提供了过多错误信息
            return Err("参数不足")
        }
        let query = args[1].to_owned();
        let file_path = args[2].to_owned();
        let ignore_case = env::var("IGNORE_CASE").is_ok();
        //如果设置，true，没设置false
        Ok(Config{
            query,
            file_path,
            ignore_case,
        })//需要所有权
    }
}

pub fn run(config:Config)->Result<(),Box<dyn Error>>{
    let str = fs::read_to_string(config.file_path)?;

    let results=if !config.ignore_case {
        search(&config.query, &str)
    }else {
        search_case_insensitive(&config.query, &str)
    };

    for line in results{
        println!("{line}");
    }
    Ok(())
}

pub fn search<'a>(query:&str,content:&'a str)->Vec<&'a str>{//vec与content相关
    let mut result: Vec<&str> = Vec::new();
    for line in content.lines() {
        if line.contains(query){
            result.push(line);
        }
    }
    result
}

pub fn search_case_insensitive<'a>(query:&str,content:&'a str)->Vec<&'a str>{//vec与content相关
    let query=query.to_lowercase();
    let mut result: Vec<&str> = Vec::new();
    for line in content.lines() {
        if line.to_lowercase().contains(&query){
            result.push(line);
        }
    }
    result
}

#[cfg(test)]
mod tests{
    use super::*;

    #[test]
    fn case_sensitive(){
        let query = "s";
        let content="\
bbbbb
aasa
ddd";
        assert_eq!(vec!["aasa"],search(query,content));
    }


    #[test]
    fn case_insensitive(){
        let query = "AA";
        let content="\
bbbbb
aAsa
ddd";
        assert_eq!(vec!["aAsa"],search_case_insensitive(query,content));
    }
}